package com.fowo.api.syncAmazon.core.sync;

import cn.hutool.core.util.StrUtil;
import com.amazon.spapi.api.ListingsApi;
import com.amazon.spapi.client.ApiException;
import com.amazon.spapi.model.listingsitems.Item;
import com.amazon.spapi.model.reports.CreateReportSpecification;
import com.amazon.spapi.model.reports.Report;
import com.amazon.spapi.model.reports.ReportDocument;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fowo.api.entity.ShopInfo;
import com.fowo.api.entity.SysRegion;
import com.fowo.api.entity.TmpListing;
import com.fowo.api.service.impl.ShopInfoServiceImpl;
import com.fowo.api.service.impl.SysRegionServiceImpl;
import com.fowo.api.service.impl.TmpListingServiceImpl;
import com.fowo.api.syncAmazon.core.AbstractAmazonSyncData;
import com.fowo.api.syncAmazon.core.ReportApiType;
import com.fowo.api.syncAmazon.entity.ApiDefine;
import com.fowo.api.syncAmazon.entity.ApiRequestLog;
import com.fowo.api.syncAmazon.mapper.ListingMapper;
import com.fowo.api.syncAmazon.util.AmzDateUtils;
import com.fowo.api.syncAmazon.util.GeneralUtil;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.*;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @fileName: ListingFatherSync
 * @Description: 代码目的，作用，如何工作
 * @Author: yyf
 * @Date: 2024/2/18 0018 10:57
 */
@Slf4j
@Component
public class ListingFatherSync extends AbstractAmazonSyncData {
    @Resource
    private ShopInfoServiceImpl shopInfoServiceImpl;
    @Resource
    private TmpListingServiceImpl tmpListingService;
    @Resource
    private SysRegionServiceImpl sysRegionService;
    private RateLimiter rateLimiter = RateLimiter.create(4);
    @Resource
    private ListingMapper listingMapper;
    private ApiDefine apiDefine = ApiDefine.builder()
            .apiCode("listing")
            .initdate(1)
            .timeInterval(1)
            .timeIntervalType("day").build();

    @Override
    protected ApiDefine setApiDefine() {
        return this.apiDefine;
    }
    private List<SysRegion> sysRegions = null;

    @Override
    protected void requestData() throws Exception {
        // 获取卖家账号信息
        String platform = "Amazon";
        this.getAuthority(platform);
        // 查询该账号下所有店铺
        LambdaQueryWrapper<ShopInfo> shopInfosWrapper = new LambdaQueryWrapper<>();
        shopInfosWrapper.eq(ShopInfo::getPlatform,"Amazon")
                .eq(ShopInfo::getSellerAuthStatus,"SQ01");
        List<ShopInfo> shopInfoList = shopInfoServiceImpl.list(shopInfosWrapper);

        // 查询该店铺国家关联的id
        List<String> shopByCountry = shopInfoList.stream().map(ShopInfo::getCountry).collect(Collectors.toList());
        sysRegions = sysRegionService.getBaseMapper().selectList(Wrappers.lambdaQuery(SysRegion.class)
                .in(SysRegion::getName, shopByCountry)
                .eq(SysRegion::getPlatform,"Amazon"));

        // 清空临时表
        listingMapper.deleteAll();

        //请求报告
        for (ShopInfo shopInfo : shopInfoList) {
            //创建报告 -查询参数
            List<String> marketplaceIds = Arrays.asList(shopInfo.getMarketplaceId().split(","));
            CreateReportSpecification body = new CreateReportSpecification();
            body.setReportType(ReportApiType.GET_MERCHANT_LISTINGS_ALL_DATA);
            body.setMarketplaceIds(marketplaceIds);
            // 获取拉取的时间区间
            body.setDataStartTime(AmzDateUtils.getOffsetDateTimeUTC(startTime));
            body.setDataEndTime(AmzDateUtils.getOffsetDateTimeUTC(endTime));

            // 第一步 创建报告
            logger.info("正在获取店铺："+shopInfo.getId()+" 的："+ReportApiType.GET_MERCHANT_LISTINGS_ALL_DATA+"报告");
            final String reportId = retryCreateReport(shopInfo, body);
            // 第二步 检验报告是否完成
            Report report = retryCheckReport(shopInfo, reportId);
            // 第三步 获取报告连接
            ReportDocument reportDocument = getReportDocument(shopInfo,report.getReportDocumentId());
            logger.info(reportDocument.getUrl());

            if (reportDocument != null) {
                String compressionAlgorithm = reportDocument.getCompressionAlgorithm() != null ? reportDocument.getCompressionAlgorithm().getValue() : null;
                BufferedReader reader = this.getAndUnzipReport(reportDocument.getUrl(), compressionAlgorithm);
                try {
                    download(reader, shopInfo);
                }catch (Exception ex){
                    logger.error("缓存至临时表异常："+ex);
                    throw new RuntimeException(ex);
                }finally {
                    reader.close();
                }
            }
        }
    }

    @Override
    protected <T> void download(T readerTmp, ShopInfo shop) throws IOException, IllegalArgumentException {
        BufferedReader reader = null;
        if (readerTmp instanceof BufferedReader){
            try {
                reader = (BufferedReader)readerTmp;
            }catch (Exception e){
                throw new RuntimeException(e);
            }
        }

        int lineNumber = 0;
        String line;
        List<TmpListing> list = new ArrayList<TmpListing>();
        Map<String,Integer> titleList = new HashMap<String,Integer>();
        Set<String> skuSet = new HashSet<String>();

        while ((line = reader.readLine()) != null){
            TmpListing tmp = new TmpListing();
            String[] info = line.split("\t");
            if(lineNumber == 0){
                for (int i = 0;i < info.length;i++){
                    titleList.put(info[i],i);
                }
            }else {
                if(info.length < titleList.size()){
                    continue;
                }
                Map<String, Object> fields = this.getFieldsFromInfo(info, titleList);

                tmp.setName((String)fields.get("item-name"));
                tmp.setDescription((String)fields.get("item-description"));
                tmp.setListingId((String)fields.get("listing-id"));

                String sku = fields.get("seller-sku").toString();
                if(sku == null || skuSet.contains(sku.trim().toUpperCase()))continue;
                skuSet.add(sku.trim().toUpperCase());
                tmp.setSellerSku(sku);

                String price = fields.get("price").toString();
                if (StrUtil.isNotEmpty(price)){
                    try {
                        tmp.setPrice(new BigDecimal(price));
                    } catch (Exception e) {
                        logger.error("SKU:"+sku+"的价格("+price+")格式化错误！");
                        continue;
                    }
                }

                tmp.setQuantity(GeneralUtil.getIntegerValue(fields.get("quantity")));

                String openDateStr = fields.get("open-date").toString();
                Date openDate = null;
                if (StrUtil.isNotEmpty(openDateStr)) {
                    // 2019-12-06 03:30:06 PST, 05/09/2018 09:58:06 MEST
                    SimpleDateFormat sdf1 = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
                    //是否是日本站点
                    if ("JP".equals(shop.getRegion())) {
                        sdf1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                        sdf1.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));
                    }
                    try {
                        if(openDateStr.length()>19){
                            openDate = sdf1.parse(openDateStr.substring(0, 19));// 2019-12-06 03:30:06

                        } else {
                            System.out.println(openDateStr);
                        }
                    } catch (ParseException e) {
                        if(openDateStr.length()>19){
                            openDate = GeneralUtil.getDatez(openDateStr.substring(0, 19));
                        } else {
                            System.out.println(openDateStr);
                        }
                    }
                }
                if (openDate!=null) {
                    tmp.setOpenDate(openDate);
                }

                tmp.setImageUrl((String)fields.get("image-url"));
                tmp.setItemIsMarketplace((String)fields.get("item-is-marketplace"));
                tmp.setProductType((String)fields.get("product-id-type"));
                String zshopShippingFee = fields.get("zshop-shipping-fee").toString();
                if (StrUtil.isNotEmpty(zshopShippingFee)){
                    try {
                        tmp.setZshopShippingFee(new BigDecimal(zshopShippingFee));
                    } catch (Exception e) {
                        logger.error("SKU:"+sku+"的运费("+zshopShippingFee+")格式化错误！");
                        continue;
                    }
                }
                tmp.setItemNote((String)fields.get("item-note"));
                tmp.setItemCondition((String)fields.get("item-condition"));
                tmp.setZshopCategory((String)fields.get("zshop-category1"));
                tmp.setZshopBrowsePath((String)fields.get("zshop-browse-path"));
                tmp.setZshopStorefrontFeature((String)fields.get("zshop-storefront-feature"));
                tmp.setAsin((String)fields.get("asin1"));
                tmp.setWillShipInternationally((String)fields.get("will-ship-internationally"));
                tmp.setExpeditedShipping((String)fields.get("expedited-shipping"));
                tmp.setProductId((String)fields.get("product-id"));
                tmp.setBidForFeaturedPlacement((String)fields.get("bid-for-featured-placement"));
                tmp.setAddDelete((String)fields.get("add-delete"));
                tmp.setPendingQuantity((String)fields.get("pending-quantity"));
                tmp.setFulfillmentChannel((String)fields.get("fulfillment-channel"));
                tmp.setMerchantShippingGroup((String)fields.get("merchant-shipping-group"));

                tmp.setStatus((String) fields.get("status"));
                if(tmp.getStatus() != null && tmp.getStatus().equals("Incomplete"))continue;
                switch (tmp.getStatus()){
                    case "Active":
                        tmp.setStatus("1");
                        break;
                    default:
                        tmp.setStatus("0");
                        break;
                }

                tmp.setCreateTime(new Date());
                tmp.setLastUpdateTime(new Date());
                tmp.setCountry(shop.getCountry());

                // 关联
                Optional<SysRegion> exist = sysRegions.stream().filter(r -> r.getName().equals(shop.getCountry())).findAny();
                if(exist.isPresent()){
                    tmp.setRegion(exist.get().getId());
                    tmp.setCurrency(exist.get().getCurrency());
                }

                tmp.setSid(shop.getId());
                list.add(tmp);
            }
            lineNumber++;
        }
        // 写入同步数据量
        Integer dataVolume = apiRequestLog.getDataVolume() == null ? 0 : apiRequestLog.getDataVolume();
        apiRequestLog.setDataVolume(dataVolume+list.size());
        // fnsku
        try {
            logger.info("开始插入来自listing接口的FNSKU");
            setListingFnsku(list,shop);
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }

        tmpListingService.saveBatch(list);
    }

    @Override
    protected void updateOrInsertData() {
        logger.info("---正在新增或更新----");
        listingMapper.updateToListingFather();
        listingMapper.insertToListingFather();

    }

    private void setListingFnsku(List<TmpListing> list,ShopInfo shop) throws InterruptedException,ApiException {
        String sellerId = shop.getSellerId();
        if(!sellerId.startsWith("A")){
            return;
        }
        ListingsApi listingsApi = amazonUtil.getListingsApi(entityAuthority,shop);
        int size = list.size();
        for(TmpListing tmpListing : list){
            if(StrUtil.isBlank(tmpListing.getSellerSku())){
                continue;
            }
            List<String> marketplaceIds = new ArrayList<>();
            marketplaceIds.add(shop.getMarketplaceId());
            String issueLocale = null;
            List<String> includedData = null;

            boolean isContinue = true;
            int i = 3;
            while (isContinue){
                Item response = null;
                rateLimiter.acquire();

                try {
                    logger.info("----正在获取卖家："+sellerId+"-msku:"+tmpListing.getSellerSku()+"的listing信息，还剩："+ size-- + "----");
                    response = listingsApi.getListingsItem(sellerId, tmpListing.getSellerSku(), marketplaceIds, issueLocale, includedData);
                } catch (ApiException e) {
                    // 超时重试机制
                    if (e.getCode() == 429){

                        Thread.sleep(60000);
                        response = listingsApi.getListingsItem(sellerId, tmpListing.getSellerSku(), marketplaceIds, issueLocale, includedData);
                    }else if(e.getMessage().contains("timeout")){
                        logger.info("--出现超时异常，正在重试--");
                        isContinue = true;
                        Thread.sleep(10000);
                        i--;
                        if (i == 0){
                            logger.info("三次重试均失败");
                            throw new RuntimeException(e);
                        }else {
                            continue;
                        }
                    }else{
                        apiRequestLog.setErrorMessage("订单获取发生异常："+e.getMessage()+e.getResponseBody());
                        apiRequestLog.setStatus(ApiRequestLog.FAIL);
                        apiRequestLogService.getBaseMapper().updateById(apiRequestLog);
                        throw new RuntimeException(e);
                    }
                }
                isContinue = false;
                tmpListing.setFnsku(Optional.of(response.getSummaries()).map(s -> s.get(0)).map(s ->s.getFnSku()).orElse(null));
            }
        }
    }
}
